package cloudjunit;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import Common.TraceWriter;

import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.model.WorkflowExecution;

import cloudjunit.UnitTestWorkflowClientExternal;
import cloudjunit.UnitTestWorkflowClientExternalFactory;
import cloudjunit.UnitTestWorkflowClientExternalFactoryImpl;
import dynamojunit.TestClassTable;
import dynamojunit.UserSessionTable;
import dynamojunit.WorkflowTable;

public class WorkflowExecutionStarter {
	
	private final String sessionId;
	private final String remoteJarFilePath;
	private String workFlowId;
	
	UserSessionTable sessionTable;
	
	public WorkflowExecutionStarter(String sessionId, String remoteJarFilePath)
	{
		this.sessionId = sessionId;
		this.remoteJarFilePath = remoteJarFilePath;
		this.workFlowId = null;
		
		sessionTable = new UserSessionTable(true);
	}
	
	private void addWorkFlowIdtoCurrentSession(String workFlowId)
	{
		TraceWriter.trace("initWorkflowStatus: initializing workflow..");
		sessionTable.insertSessionWorkFlow(sessionId, workFlowId);
	}
	
	public void go()
	{
		AmazonSimpleWorkflow swfService = Config.createSWFClient();
        String domain = Config.data.domain;

        UnitTestWorkflowClientExternalFactory clientFactory = new UnitTestWorkflowClientExternalFactoryImpl(swfService,domain);
        UnitTestWorkflowClientExternal workflow = clientFactory.getClient();
        
        // Start Wrokflow Execution
        workflow.startJarTestsFlow(remoteJarFilePath);
        
        // WorkflowExecution is available after workflow creation 
        WorkflowExecution workflowExecution = workflow.getWorkflowExecution();
        workFlowId = workflowExecution.getWorkflowId();	// run id is the correct wfid 
        
        TraceWriter.trace("Started cloudunit workflow with workflowId=\"" + workflowExecution.getWorkflowId()+ "\" and runId=\"" + workflowExecution.getRunId() + "\"");
     
        // TODO cancel workflow in case of failure
        addWorkFlowIdtoCurrentSession(workFlowId);
        
        TraceWriter.trace("FINISHED starting new workflow.");
	}
	
	////////////////////////////////////////////////

    public static void main(String[] args) throws Exception
    {
    	Config.initConfigWithConfigFile();
    	
    	initTablesIfNeededParrallel();
    	
    	WorkflowExecutionStarter workflow_starter = new WorkflowExecutionStarter("FAKESESSIONID","test.jar");
    	workflow_starter.go();
    }
    
    private static void initTablesIfNeededParrallel()
    {
    	try
    	{
    		TraceWriter.trace("initTablesIfNeededParrallel started.");
    		final int TABLES_NUM = 3;
	    	BlockingQueue<Runnable> queue =  new ArrayBlockingQueue<Runnable>(TABLES_NUM);
	    	ThreadPoolExecutor pool = new ThreadPoolExecutor(TABLES_NUM, TABLES_NUM, 2, TimeUnit.MINUTES, queue);
	    	
	    	pool.submit(new Runnable() {
				@Override
				public void run() {
					try {
						new UserSessionTable(true);
					} catch (Exception ex) {
					}
				}
			});
	    	pool.submit(new Runnable() {
				@Override
				public void run() {
					try {
						new WorkflowTable(true);
					} catch (Exception ex) {
					}
				}
			});
	    	pool.submit(new Runnable() {
				@Override
				public void run() {
					try {
						new TestClassTable(true);
					} catch (Exception ex) {
					}
				}
			});
	    	/////////////
	    	
	    	pool.shutdown();
	    	TraceWriter.trace("initTablesIfNeededParrallel awaiting...");
	    	pool.awaitTermination(2, TimeUnit.MINUTES);
    	}
    	catch (Exception e)
    	{
    		e.printStackTrace();
    	}
    	TraceWriter.trace("initTablesIfNeededParrallel finished.");
    }

}